{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_first_function():\n",
    "    print(\"Hello world!\")\n",
    "\n",
    "\n",
    "print(f\"type: {type(my_first_function)}\")\n",
    "\n",
    "my_first_function()  # Calling a function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greet_us(name1, name2):\n",
    "    print(f\"Hello {name1} and {name2}!\")\n",
    "\n",
    "\n",
    "greet_us(\"John Doe\", \"Superman\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function with return value\n",
    "def strip_and_lowercase(original):\n",
    "    modified = original.strip().lower()\n",
    "    return modified\n",
    "\n",
    "\n",
    "uggly_string = \"  MixED CaSe \"\n",
    "pretty = strip_and_lowercase(uggly_string)\n",
    "print(f\"pretty: {pretty}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Keyword arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_fancy_calculation(first, second, third):\n",
    "    return first + second - third\n",
    "\n",
    "\n",
    "print(my_fancy_calculation(3, 2, 1))\n",
    "\n",
    "print(my_fancy_calculation(first=3, second=2, third=1))\n",
    "\n",
    "# With keyword arguments you can mix the order\n",
    "print(my_fancy_calculation(third=1, first=3, second=2))\n",
    "\n",
    "# You can mix arguments and keyword arguments but you have to start with arguments\n",
    "print(my_fancy_calculation(3, third=1, second=2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Default arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_person_info(name, age, job=None, salary=300):\n",
    "    info = {\"name\": name, \"age\": age, \"salary\": salary}\n",
    "\n",
    "    # Add 'job' key only if it's provided as parameter\n",
    "    if job:\n",
    "        info.update(dict(job=job))\n",
    "\n",
    "    return info\n",
    "\n",
    "\n",
    "person1 = create_person_info(\"John Doe\", 82)  # use default values for job and salary\n",
    "person2 = create_person_info(\"Lisa Doe\", 22, \"hacker\", 10000)\n",
    "print(person1)\n",
    "print(person2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Don't use mutable objects as default arguments!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def append_if_multiple_of_five(number, magical_list=[]):\n",
    "    if number % 5 == 0:\n",
    "        magical_list.append(number)\n",
    "    return magical_list\n",
    "\n",
    "\n",
    "print(append_if_multiple_of_five(100))\n",
    "print(append_if_multiple_of_five(105))\n",
    "print(append_if_multiple_of_five(123))\n",
    "print(append_if_multiple_of_five(123, []))\n",
    "print(append_if_multiple_of_five(123))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here's how you can achieve desired behavior:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def append_if_multiple_of_five(number, magical_list=None):\n",
    "    if not magical_list:\n",
    "        magical_list = []\n",
    "    if number % 5 == 0:\n",
    "        magical_list.append(number)\n",
    "    return magical_list\n",
    "\n",
    "\n",
    "print(append_if_multiple_of_five(100))\n",
    "print(append_if_multiple_of_five(105))\n",
    "print(append_if_multiple_of_five(123))\n",
    "print(append_if_multiple_of_five(123, []))\n",
    "print(append_if_multiple_of_five(123))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Docstrings\n",
    "Strings for documenting your functions, methods, modules and variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def print_sum(val1, val2):\n",
    "    \"\"\"Function which prints the sum of given arguments.\"\"\"\n",
    "    print(f\"sum: {val1 + val2}\")\n",
    "\n",
    "\n",
    "print(help(print_sum))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_sum(val1, val2):\n",
    "    \"\"\"This is a longer docstring defining also the args and the return value.\n",
    "\n",
    "    Args:\n",
    "        val1: The first parameter.\n",
    "        val2: The second parameter.\n",
    "\n",
    "    Returns:\n",
    "        The sum of val1 and val2.\n",
    "\n",
    "    \"\"\"\n",
    "    return val1 + val2\n",
    "\n",
    "\n",
    "print(help(calculate_sum))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### [`pass`](https://docs.python.org/3/reference/simple_stmts.html#the-pass-statement) statement\n",
    "`pass` is a statement which does nothing when it's executed. It can be used e.g. a as placeholder to make the code syntatically correct while sketching the functions and/or classes of your application. For example, the following is valid Python. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_function(some_argument):\n",
    "    pass\n",
    "\n",
    "\n",
    "def my_other_function():\n",
    "    pass"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
